package com.bocloud.cmp.driver.providers.os;

import java.util.List;

import org.openstack4j.model.compute.Flavor;
import org.openstack4j.model.compute.Server;
import org.openstack4j.model.compute.ext.AvailabilityZone;
import org.openstack4j.model.compute.ext.Hypervisor;
import org.openstack4j.model.image.Image;
import org.openstack4j.model.network.Network;
import org.openstack4j.model.network.Port;
import org.openstack4j.model.network.Router;
import org.openstack4j.model.storage.block.Volume;
import org.openstack4j.model.storage.block.VolumeSnapshot;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.bocloud.cmp.driver.convertor.BeanConvert;
import com.bocloud.cmp.driver.convertor.os.ConverPort;
import com.bocloud.cmp.driver.convertor.os.ConvertFlavor;
import com.bocloud.cmp.driver.convertor.os.ConvertHyperV;
import com.bocloud.cmp.driver.convertor.os.ConvertImage;
import com.bocloud.cmp.driver.convertor.os.ConvertNetworks;
import com.bocloud.cmp.driver.convertor.os.ConvertRoute;
import com.bocloud.cmp.driver.convertor.os.ConvertServer;
import com.bocloud.cmp.driver.convertor.os.ConvertSnapshots;
import com.bocloud.cmp.driver.convertor.os.ConvertVolumes;
import com.bocloud.cmp.driver.providers.LocationDriver;
import com.bocloud.cmp.driver.utils.Configure;
import com.bocloud.cmp.driver.zteadapter.ZTEHostSystemModel;
import com.bocloud.cmp.driver.zteadapter.ZTEHttpRequest;
import com.bocloud.cmp.driver.zteadapter.ZTEHypervisor;
import com.bocloud.cmp.enums.VMStatus;
import com.bocloud.cmp.model.FlavorModel;
import com.bocloud.cmp.model.HostModel;
import com.bocloud.cmp.model.ImageModel;
import com.bocloud.cmp.model.NetworkModel;
import com.bocloud.cmp.model.OSSyncModel;
import com.bocloud.cmp.model.PortModel;
import com.bocloud.cmp.model.RegionModel;
import com.bocloud.cmp.model.RouteModel;
import com.bocloud.cmp.model.ServerModel;
import com.bocloud.cmp.model.SnapshotModel;
import com.bocloud.cmp.model.VolumeModel;
import com.bocloud.common.model.BsmResult;
import com.google.common.collect.Lists;

public class OSLocationDriver extends OSDriver implements LocationDriver {

    private static final Logger logger = LoggerFactory.getLogger(OSLocationDriver.class);

    private final String isZXPlatform = "zx.openstack.isZXPlatform";
    private final String zxurl = "zx.openstack.url";
    private final String zxuuid = "zx.openstack.uuid";

    /**
     * 
     */
    public OSLocationDriver() {
        super();
    }

    public OSLocationDriver(String endpoint, String username, String password, String tenant, String domain,
            String project, Version version) {
        super(endpoint, username, password, tenant, domain, project, version);
    }

    @Override
    public BsmResult listRegions() {
        return null;
    }

    @Override
    public BsmResult sync() {
        Configure config = new Configure("config/application.properties");
        OSSyncModel ossyncModel = new OSSyncModel();
        List<OSSyncModel> ossyncModels = Lists.newArrayList();
        List<? extends AvailabilityZone> availabilityzones = Lists.newArrayList();
        List<? extends Hypervisor> hyperVs = Lists.newArrayList();
        List<? extends Server> servers = Lists.newArrayList();
        List<? extends Network> networks = Lists.newArrayList();
        List<? extends Volume> volumes = Lists.newArrayList();
        List<? extends VolumeSnapshot> snapshots = Lists.newArrayList();
        List<? extends Image> images = Lists.newArrayList();
        List<? extends Flavor> flavors = Lists.newArrayList();
        List<? extends Port> ports = Lists.newArrayList();
        List<? extends Router> routers = Lists.newArrayList();

        if (!this.accessable()) {
            logger.error(this.getError());
            return new BsmResult(false, this.getError());
        }
        availabilityzones = this.getClient().compute().zones().list();

        if (Boolean.parseBoolean(config.getkey(isZXPlatform))) {
            ZTEHttpRequest zxhttpRequest = new ZTEHttpRequest(config.getkey(zxurl), config.getkey(zxuuid));
            ossyncModel.setHostModels(convert(zxhttpRequest.getHost()));
        } else {
            hyperVs = this.getClient().compute().hypervisors().list();
            if (null != hyperVs && !hyperVs.isEmpty()) {
                BeanConvert<HostModel, Hypervisor> convertHyperV = new ConvertHyperV();
                ossyncModel.setHostModels(convertHyperV.convertList(hyperVs));
            }
        }
        servers = this.getClient().compute().servers().listAll(true);
        networks = this.getClient().networking().network().list();
        volumes = this.getClient().blockStorage().volumes().listAll();
        snapshots = this.getClient().blockStorage().snapshots().list();
        images = this.getClient().images().listAll();
        flavors = this.getClient().compute().flavors().list(true);
        ports = this.getClient().networking().port().list();// add by ouywl 2017
        routers = this.getClient().networking().router().list();

        if (null != availabilityzones && !availabilityzones.isEmpty()) {
            List<RegionModel> regions = Lists.newArrayList();
            for (AvailabilityZone aZones : availabilityzones) {
                RegionModel region = new RegionModel();
                region.setCode(aZones.getZoneName());
                region.setName(aZones.getZoneName());
                regions.add(region);
            }
            ossyncModel.setRegions(regions);

            if (null != servers && !servers.isEmpty()) {
                BeanConvert<ServerModel, Server> convertServer = new ConvertServer();
                ossyncModel.setServerModels(convertServer.convertList(servers));
            }
            if (null != networks && !networks.isEmpty()) {
                BeanConvert<NetworkModel, Network> convertNetworks = new ConvertNetworks();
                ossyncModel.setNetworkModels(convertNetworks.convertList(networks));
            }
            if (null != volumes && !volumes.isEmpty()) {
                BeanConvert<VolumeModel, Volume> convertVolumes = new ConvertVolumes();
                ossyncModel.setVolumeModels(convertVolumes.convertList(volumes));
            }
            if (null != snapshots && !snapshots.isEmpty()) {
                BeanConvert<SnapshotModel, VolumeSnapshot> convertSnapshot = new ConvertSnapshots();
                ossyncModel.setSnapshotModels(convertSnapshot.convertList(snapshots));
            }
            if (null != images && !images.isEmpty()) {
                BeanConvert<ImageModel, Image> convertImage = new ConvertImage();
                ossyncModel.setImageModels(convertImage.convertList(images));
            }
            if (null != flavors && !flavors.isEmpty()) {
                BeanConvert<FlavorModel, Flavor> convertFlavor = new ConvertFlavor();
                ossyncModel.setFlavorModels(convertFlavor.convertList(flavors));
            }
            if (null != ports && !ports.isEmpty()) {
                BeanConvert<PortModel, Port> convertPort = new ConverPort();
                ossyncModel.setPortModels(convertPort.convertList(ports));
            }
            if (null != routers && !routers.isEmpty()) {
                BeanConvert<RouteModel, Router> convertRoute = new ConvertRoute();
                ossyncModel.setRouteModels(convertRoute.convertList(routers));
            }
            ossyncModels.add(ossyncModel);
            return new BsmResult(true, ossyncModels, "success");
        }
        return new BsmResult(false, "同步失败");
    }

    @Override
    public BsmResult listZones(String region) {
        return null;
    }

    /**
     * 转换函数
     * 
     * @param zxHostSystemModel
     * @return
     */
    private List<HostModel> convert(ZTEHostSystemModel zxHostSystemModel) {
        List<HostModel> hostModels = Lists.newArrayList();
        if (null == zxHostSystemModel || null == zxHostSystemModel.getHypervisors()) {
            return null;
        }
        for (ZTEHypervisor hypervisor : zxHostSystemModel.getHypervisors()) {
            HostModel hostModel = new HostModel();
            hostModel.setUuid(hypervisor.getHypervisorId());
            hostModel.setName(hypervisor.getHypervisorHostname());
            hostModel.setHostIp(hypervisor.getHostIp());
            if ("active".equalsIgnoreCase(hypervisor.getStatus())) {
                hostModel.setStatus(VMStatus.RUNNING.name());
                hostModel.setPowerState(VMStatus.RUNNING.name());
            } else if ("start".equalsIgnoreCase(hypervisor.getStatus())) {
                hostModel.setStatus(VMStatus.STARTING.name());
                hostModel.setPowerState(VMStatus.STARTING.name());
            } else if ("restart".equalsIgnoreCase(hypervisor.getStatus())) {
                hostModel.setStatus(VMStatus.RESTARTING.name());
                hostModel.setPowerState(VMStatus.RESTARTING.name());
            } else if ("offline".equalsIgnoreCase(hypervisor.getStatus())) {
                hostModel.setStatus(VMStatus.SYNSEXCEPTION.name());
                hostModel.setPowerState(VMStatus.SYNSEXCEPTION.name());
            } else if ("shutoff".equalsIgnoreCase(hypervisor.getStatus())) {
                hostModel.setStatus(VMStatus.STOPPED.name());
                hostModel.setPowerState(VMStatus.STOPPED.name());
            } else if ("inshutdown".equalsIgnoreCase(hypervisor.getStatus())) {
                hostModel.setStatus(VMStatus.STOPPING.name());
                hostModel.setPowerState(VMStatus.STOPPING.name());
            } else if ("unkown".equalsIgnoreCase(hypervisor.getStatus())) {
                hostModel.setStatus(VMStatus.SYNSEXCEPTION.name());
                hostModel.setPowerState(VMStatus.SYNSEXCEPTION.name());
            }
            hostModel.setVendor(hypervisor.getExtra().getCpuModel());
            hostModel.setCatalog("OPENSTACK");
            hostModel.setCpuNum(Integer.parseInt(hypervisor.getExtra().getCpu_num()));
            hostModel.setMemTotal(Long.parseLong(hypervisor.getExtra().getMemsum()));
            hostModel.setVmNum(Integer.parseInt(hypervisor.getRunningVms()));
            hostModel.setCpuModel(hypervisor.getExtra().getCpuModel());
            hostModel.setCpuCore(Integer.parseInt(hypervisor.getExtra().getPhy_cpuNum()));
            hostModel.setCpuTotal(Long.parseLong(hypervisor.getExtra().getCpu_num()));
            hostModel.setDiskTotal(0L);// 目前接口里面没有这个值
            hostModel.setCpuUsed((long) (Long.parseLong(hypervisor.getExtra().getCpu_num())
                    * Float.parseFloat(hypervisor.getExtra().getVcpus_used_rate())) / 100);
            hostModel.setMemUsed((long) (Long.parseLong(hypervisor.getExtra().getMemsum())
                    * Float.parseFloat(hypervisor.getExtra().getMemory_mb_used_rate())) / 100);
            hostModel.setDiskUsed(0L);
            hostModels.add(hostModel);
        }
        return hostModels;
    }

}
